"""
基础策略类

提供所有策略的抽象基类和通用功能。
"""

from abc import ABC, abstractmethod
from enum import Enum
from typing import Dict, List, Any, Optional, Union
from datetime import datetime, timedelta
from dataclasses import dataclass, field
import pandas as pd
import numpy as np


class StrategyType(Enum):
    """策略类型枚举"""
    FACTOR = "factor"  # 因子策略
    TECHNICAL = "technical"  # 技术分析策略
    MACHINE_LEARNING = "machine_learning"  # 机器学习策略
    PORTFOLIO = "portfolio"  # 组合策略
    ARBITRAGE = "arbitrage"  # 套利策略
    MOMENTUM = "momentum"  # 动量策略
    MEAN_REVERSION = "mean_reversion"  # 均值回归策略
    PAIRS_TRADING = "pairs_trading"  # 配对交易策略


class StrategyStatus(Enum):
    """策略状态枚举"""
    INACTIVE = "inactive"  # 未激活
    ACTIVE = "active"  # 激活
    PAUSED = "paused"  # 暂停
    ERROR = "error"  # 错误
    STOPPED = "stopped"  # 停止


class SignalType(Enum):
    """信号类型枚举"""
    BUY = "buy"  # 买入信号
    SELL = "sell"  # 卖出信号
    HOLD = "hold"  # 持有信号
    CLOSE = "close"  # 平仓信号


class RiskLevel(Enum):
    """风险等级枚举"""
    LOW = "low"  # 低风险
    MEDIUM = "medium"  # 中等风险
    HIGH = "high"  # 高风险
    EXTREME = "extreme"  # 极高风险


@dataclass
class Signal:
    """交易信号数据类"""
    symbol: str  # 标的代码
    signal_type: SignalType  # 信号类型
    strength: float  # 信号强度 (0-1)
    confidence: float  # 信号置信度 (0-1)
    timestamp: datetime  # 信号时间
    price: Optional[float] = None  # 信号价格
    volume: Optional[int] = None  # 建议交易量
    stop_loss: Optional[float] = None  # 止损价格
    take_profit: Optional[float] = None  # 止盈价格
    metadata: Dict[str, Any] = field(default_factory=dict)  # 额外信息


@dataclass
class Position:
    """持仓信息数据类"""
    symbol: str  # 标的代码
    quantity: float  # 持仓数量
    avg_price: float  # 平均成本价
    current_price: float  # 当前价格
    market_value: float  # 市值
    unrealized_pnl: float  # 未实现盈亏
    realized_pnl: float  # 已实现盈亏
    entry_time: datetime  # 建仓时间
    last_update: datetime  # 最后更新时间


@dataclass
class StrategyConfig:
    """策略配置基类"""
    name: str  # 策略名称
    description: str  # 策略描述
    strategy_type: StrategyType  # 策略类型
    risk_level: RiskLevel  # 风险等级
    max_position_size: float = 0.1  # 最大仓位比例
    stop_loss_pct: float = 0.05  # 止损百分比
    take_profit_pct: float = 0.15  # 止盈百分比
    rebalance_frequency: str = "daily"  # 再平衡频率
    benchmark: str = "000300.SH"  # 基准指数
    universe: List[str] = field(default_factory=list)  # 股票池
    start_date: Optional[datetime] = None  # 开始日期
    end_date: Optional[datetime] = None  # 结束日期
    initial_capital: float = 1000000.0  # 初始资金
    commission_rate: float = 0.0003  # 手续费率
    slippage_rate: float = 0.001  # 滑点率
    min_trade_amount: float = 1000.0  # 最小交易金额
    max_trade_amount: float = 100000.0  # 最大交易金额
    parameters: Dict[str, Any] = field(default_factory=dict)  # 策略参数


@dataclass
class StrategyMetrics:
    """策略指标数据类"""
    total_return: float  # 总收益率
    annual_return: float  # 年化收益率
    volatility: float  # 波动率
    sharpe_ratio: float  # 夏普比率
    max_drawdown: float  # 最大回撤
    win_rate: float  # 胜率
    profit_loss_ratio: float  # 盈亏比
    total_trades: int  # 总交易次数
    profitable_trades: int  # 盈利交易次数
    losing_trades: int  # 亏损交易次数
    avg_trade_return: float  # 平均交易收益率
    avg_holding_period: float  # 平均持仓天数
    turnover_rate: float  # 换手率
    information_ratio: float  # 信息比率
    calmar_ratio: float  # 卡玛比率
    sortino_ratio: float  # 索提诺比率
    var_95: float  # 95% VaR
    cvar_95: float  # 95% CVaR
    beta: float  # 贝塔系数
    alpha: float  # 阿尔法系数
    tracking_error: float  # 跟踪误差
    start_date: datetime  # 开始日期
    end_date: datetime  # 结束日期
    last_update: datetime  # 最后更新时间


class BaseStrategy(ABC):
    """基础策略抽象类"""
    
    def __init__(self, config: StrategyConfig):
        """
        初始化策略
        
        Args:
            config: 策略配置
        """
        self.config = config
        self.status = StrategyStatus.INACTIVE
        self.positions: Dict[str, Position] = {}
        self.signals: List[Signal] = []
        self.metrics: Optional[StrategyMetrics] = None
        self.created_at = datetime.now()
        self.last_update = datetime.now()
        self.error_message: Optional[str] = None
        
        # 策略运行状态
        self._is_initialized = False
        self._last_signal_time: Optional[datetime] = None
        self._trade_count = 0
        self._total_pnl = 0.0
        
        # 数据缓存
        self._price_data: Dict[str, pd.DataFrame] = {}
        self._indicator_cache: Dict[str, Any] = {}
    
    @abstractmethod
    async def initialize(self) -> bool:
        """
        初始化策略
        
        Returns:
            bool: 初始化是否成功
        """
        pass
    
    @abstractmethod
    async def generate_signals(self, data: Dict[str, pd.DataFrame]) -> List[Signal]:
        """
        生成交易信号
        
        Args:
            data: 市场数据，key为标的代码，value为价格数据
            
        Returns:
            List[Signal]: 交易信号列表
        """
        pass
    
    @abstractmethod
    async def update_positions(self, positions: Dict[str, Position]) -> None:
        """
        更新持仓信息
        
        Args:
            positions: 当前持仓信息
        """
        pass
    
    @abstractmethod
    async def calculate_metrics(self, returns: pd.Series, benchmark_returns: pd.Series) -> StrategyMetrics:
        """
        计算策略指标
        
        Args:
            returns: 策略收益率序列
            benchmark_returns: 基准收益率序列
            
        Returns:
            StrategyMetrics: 策略指标
        """
        pass
    
    async def start(self) -> bool:
        """
        启动策略
        
        Returns:
            bool: 启动是否成功
        """
        try:
            if not self._is_initialized:
                success = await self.initialize()
                if not success:
                    self.status = StrategyStatus.ERROR
                    self.error_message = "策略初始化失败"
                    return False
                self._is_initialized = True
            
            self.status = StrategyStatus.ACTIVE
            self.last_update = datetime.now()
            self.error_message = None
            return True
            
        except Exception as e:
            self.status = StrategyStatus.ERROR
            self.error_message = f"策略启动失败: {str(e)}"
            return False
    
    async def stop(self) -> bool:
        """
        停止策略
        
        Returns:
            bool: 停止是否成功
        """
        try:
            self.status = StrategyStatus.STOPPED
            self.last_update = datetime.now()
            return True
            
        except Exception as e:
            self.status = StrategyStatus.ERROR
            self.error_message = f"策略停止失败: {str(e)}"
            return False
    
    async def pause(self) -> bool:
        """
        暂停策略
        
        Returns:
            bool: 暂停是否成功
        """
        try:
            if self.status == StrategyStatus.ACTIVE:
                self.status = StrategyStatus.PAUSED
                self.last_update = datetime.now()
                return True
            return False
            
        except Exception as e:
            self.status = StrategyStatus.ERROR
            self.error_message = f"策略暂停失败: {str(e)}"
            return False
    
    async def resume(self) -> bool:
        """
        恢复策略
        
        Returns:
            bool: 恢复是否成功
        """
        try:
            if self.status == StrategyStatus.PAUSED:
                self.status = StrategyStatus.ACTIVE
                self.last_update = datetime.now()
                return True
            return False
            
        except Exception as e:
            self.status = StrategyStatus.ERROR
            self.error_message = f"策略恢复失败: {str(e)}"
            return False
    
    async def run_step(self, data: Dict[str, pd.DataFrame]) -> List[Signal]:
        """
        执行策略一步
        
        Args:
            data: 市场数据
            
        Returns:
            List[Signal]: 生成的交易信号
        """
        try:
            if self.status != StrategyStatus.ACTIVE:
                return []
            
            # 生成交易信号
            signals = await self.generate_signals(data)
            
            # 过滤和验证信号
            valid_signals = await self._validate_signals(signals)
            
            # 更新信号历史
            self.signals.extend(valid_signals)
            self._last_signal_time = datetime.now()
            self.last_update = datetime.now()
            
            return valid_signals
            
        except Exception as e:
            self.status = StrategyStatus.ERROR
            self.error_message = f"策略执行失败: {str(e)}"
            return []
    
    async def _validate_signals(self, signals: List[Signal]) -> List[Signal]:
        """
        验证交易信号
        
        Args:
            signals: 原始信号列表
            
        Returns:
            List[Signal]: 验证后的信号列表
        """
        valid_signals = []
        
        for signal in signals:
            # 检查信号强度和置信度
            if signal.strength < 0 or signal.strength > 1:
                continue
            if signal.confidence < 0 or signal.confidence > 1:
                continue
            
            # 检查标的代码是否在股票池中
            if self.config.universe and signal.symbol not in self.config.universe:
                continue
            
            # 检查信号时间
            if signal.timestamp > datetime.now():
                continue
            
            valid_signals.append(signal)
        
        return valid_signals
    
    def get_status(self) -> Dict[str, Any]:
        """
        获取策略状态
        
        Returns:
            Dict[str, Any]: 策略状态信息
        """
        return {
            "name": self.config.name,
            "type": self.config.strategy_type.value,
            "status": self.status.value,
            "risk_level": self.config.risk_level.value,
            "created_at": self.created_at.isoformat(),
            "last_update": self.last_update.isoformat(),
            "is_initialized": self._is_initialized,
            "last_signal_time": self._last_signal_time.isoformat() if self._last_signal_time else None,
            "trade_count": self._trade_count,
            "total_pnl": self._total_pnl,
            "position_count": len(self.positions),
            "signal_count": len(self.signals),
            "error_message": self.error_message
        }
    
    def get_positions(self) -> Dict[str, Position]:
        """
        获取当前持仓
        
        Returns:
            Dict[str, Position]: 持仓信息
        """
        return self.positions.copy()
    
    def get_recent_signals(self, limit: int = 10) -> List[Signal]:
        """
        获取最近的交易信号
        
        Args:
            limit: 返回信号数量限制
            
        Returns:
            List[Signal]: 最近的交易信号
        """
        return sorted(self.signals, key=lambda x: x.timestamp, reverse=True)[:limit]
    
    def clear_cache(self) -> None:
        """清空缓存数据"""
        self._price_data.clear()
        self._indicator_cache.clear()
    
    def update_config(self, new_config: StrategyConfig) -> bool:
        """
        更新策略配置
        
        Args:
            new_config: 新的策略配置
            
        Returns:
            bool: 更新是否成功
        """
        try:
            # 保留一些不可变的配置
            new_config.name = self.config.name
            new_config.strategy_type = self.config.strategy_type
            
            self.config = new_config
            self.last_update = datetime.now()
            
            # 清空缓存以使用新配置
            self.clear_cache()
            
            return True
            
        except Exception as e:
            self.error_message = f"配置更新失败: {str(e)}"
            return False